﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace SX.Utils
{
    /// <summary>
    /// 数据类型转换
    /// </summary>
    public static class ConvertHelper
    {
        /// <summary>
        /// 转换为int
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue">默认值 不输入则为0</param>
        /// <returns></returns>
        public static int ToInt(object obj)
        {
            return ToInt(obj, 0);
        }

        /// <summary>
        /// 转换为int
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue">默认值 不输入则为0</param>
        /// <returns></returns>
        public static int ToInt(object obj, int defaultValue)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return defaultValue;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return defaultValue;
            }
            try
            {
                return Convert.ToInt32(obj);
            }
            catch (Exception)
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// 转换为double
        /// </summary>
        /// <param name="obj">需要转换的值</param>
        /// <param name="defaultValue">默认为0</param>
        /// <returns>双精度数</returns>
        public static double ToDouble(object obj)
        {
            return ToDouble(obj, 0);
        }

        /// <summary>
        /// 转换为double
        /// </summary>
        /// <param name="obj">需要转换的值</param>
        /// <param name="defaultValue">默认为0</param>
        /// <returns>双精度数</returns>
        public static double ToDouble(object obj, double defaultValue)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return defaultValue;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return defaultValue;
            }
            try
            {
                return Convert.ToDouble(obj);
            }
            catch
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// 转换为float
        /// </summary>
        /// <param name="obj">需要转换的值</param>
        /// <param name="defaultValue">默认为0</param>
        /// <returns>双精度数</returns>
        public static float ToFloat(object obj)
        {
            return ToFloat(obj, 0);
        }

        /// <summary>
        /// 转换为double
        /// </summary>
        /// <param name="obj">需要转换的值</param>
        /// <param name="defaultValue">默认为0</param>
        /// <returns>双精度数</returns>
        public static float ToFloat(object obj, float defaultValue)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return defaultValue;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return defaultValue;
            }
            try
            {
                return float.Parse(obj.ToString());
            }
            catch
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// 转为Decimal
        /// </summary>
        /// <param name="str">表示数字的字符串</param>
        /// <returns>Decimal</returns>
        public static decimal ToDecimal(object obj)
        {
            return ToDecimal(obj, 0);
        }

        /// <summary>
        /// 转为Decimal
        /// </summary>
        /// <param name="str">表示数字的字符串</param>
        /// <returns>Decimal</returns>
        public static decimal ToDecimal(object obj, decimal defaultValue)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return defaultValue;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return defaultValue;
            }
            try
            {
                return Convert.ToDecimal(obj);
            }
            catch
            {
                return defaultValue;
            }
        }


        public static Int64 ToInt64(object obj)
        {
            return ToInt64(obj, 0);
        }

        public static Int64 ToInt64(object obj, Int64 defaultValue)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return defaultValue;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return defaultValue;
            }
            try
            {
                return Convert.ToInt64(obj);
            }
            catch (Exception)
            {
                return defaultValue;
            }
        }

        public static Int16 ToInt16(object obj, Int16 defaultValue)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return defaultValue;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return defaultValue;
            }
            try
            {
                return Convert.ToInt16(obj);
            }
            catch (Exception)
            {
                return defaultValue;
            }
        }

        public static Single ToSingle(object obj)
        {
            return ToSingle(obj, 0);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static Single ToSingle(object obj, Single defaultValue)
        {

            if (obj == null || obj == DBNull.Value)
            {
                return defaultValue;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return defaultValue;
            }
            try
            {
                return Convert.ToSingle(obj);
            }
            catch (Exception)
            {
                return defaultValue;
            }
        }

        public static string ToString(object obj)
        {
            try
            {
                return ((obj == null) || (obj == DBNull.Value)) ? "" : Convert.ToString(obj);
            }
            catch (Exception)
            {
                return "";
            }
        }

        public static DateTime ToDateTime(object obj)
        {
            return ToDateTime(obj, DateTime.MinValue);
        }

        public static DateTime ToDateTime(object obj, DateTime defaultValue)
        {

            if (obj == null || obj == DBNull.Value)
            {
                return defaultValue;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return defaultValue;
            }
            try
            {
                return Convert.ToDateTime(obj);
            }
            catch (Exception)
            {
                return defaultValue;
            }
        }

        public static TimeSpan ToTimeSpan(object obj)
        {
            return ToTimeSpan(obj, TimeSpan.MinValue);
        }

        public static TimeSpan ToTimeSpan(object obj, TimeSpan defaultValue)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return defaultValue;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return defaultValue;
            }
            try
            {
                return TimeSpan.Parse(obj.ToString());
            }
            catch (Exception)
            {
                return defaultValue;
            }
        }

        public static DateTime? ToDateTimeNull(object obj)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return null;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return null;
            }
            try
            {
                return Convert.ToDateTime(obj);
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static byte ToByte(object obj)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return byte.MinValue;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return byte.MinValue;
            }
            try
            {
                return Convert.ToByte(obj);
            }
            catch (Exception)
            {
                return byte.MinValue;
            }
        }

        public static byte[] ToByteArrayNull(object obj)
        {
            return ((obj == null) || (obj == DBNull.Value) || (obj.Equals(""))) ? null : (byte[])obj;
        }

        public static string BoolToString(bool flag)
        {
            return flag ? "1" : "0";
        }

        public static bool StringToBool(string flag)
        {
            return flag == "1";
        }

        public static Guid ToGuid(object obj)
        {
            return ToGuid(obj, Guid.Empty);
        }

        public static Guid ToGuid(object obj, Guid defaultValue)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return defaultValue;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return defaultValue;
            }
            try
            {
                return new Guid(obj.ToString());
            }
            catch (Exception)
            {
                return defaultValue;
            }
        }

        public static bool ToBool(object obj)
        {
            return ToBool(obj, false);
        }

        public static bool ToBool(object obj, bool defaultValue)
        {

            if (obj == null || obj == DBNull.Value)
            {
                return defaultValue;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return defaultValue;
            }
            if (obj is string)
            {
                var ipt = obj.ToString().Trim().ToLower();
                if (ipt == "1" || ipt == "true" || ipt == "成功" || ipt == "是" || ipt == "yes")
                {
                    return true;
                }
                else if (ipt == "0" || ipt == "false" || ipt == "失败" || ipt == "否")
                {
                    return false;
                }
            }
            try
            { 
                return Convert.ToBoolean(obj);
            }
            catch (Exception)
            {
                return defaultValue;
            }
        }

        public static bool? ToBoolNull(object obj)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return null;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return null;
            }
            try
            {
                return Convert.ToBoolean(obj);
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static DateTime? DbNullToDatetimeNull(object obj)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return null;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return null;
            }
            try
            {
                return Convert.ToDateTime(obj);
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static Int32? ToInt32Null(object obj)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return null;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return null;
            }
            try
            {
                return Convert.ToInt32(obj);
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static Int64? ToInt64Null(object obj)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return null;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return null;
            }
            try
            {
                return Convert.ToInt64(obj);
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static Decimal? ToDecimalNull(object obj)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return null;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return null;
            }
            try
            {
                return Convert.ToDecimal(obj);
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static string ToStringNull(object obj)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return null;
            }
            if (obj is string && string.IsNullOrWhiteSpace(obj.ToString()))
            {
                return null;
            }
            try
            {
                return Convert.ToString(obj);
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static T To<T>(this object input)
        {
            T value = default(T);
            try
            {
                object result = default(T);
                if (typeof(T) == typeof(int))
                    result = ToInt(input);
                else if (typeof(T) == typeof(long))
                    result = ToInt64(input);
                else if (typeof(T) == typeof(string))
                    result = ToString(input);
                else if (typeof(T) == typeof(bool))
                    result = ToBool(input);
                else if (typeof(T) == typeof(double))
                    result = System.Convert.ToDouble(input);
                else if (typeof(T) == typeof(DateTime))
                    result = System.Convert.ToDateTime(input);
                else
                    result = input;

                return (T)result; 
            }
            catch (Exception ex)
            {


            }
            return value;
        }

        public static List<int> ToInts(string str, char split = ',')
        {
            if (string.IsNullOrEmpty(str))
            {
                return new List<int>();
            }
            return str.Split(split).ToList().Select(s => s.ToInt()).ToList();
        }

        public static List<T> ToList<T>(string str, char split = ',')
        {
            if (string.IsNullOrEmpty(str))
            {
                return new List<T>();
            }
            return str.Split(split).ToList().Select(s => s.To<T>()).ToList();
        }

        /// <summary>
        ///  改变类型
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="type">The type.</param>
        /// <returns>System.Object.</returns>
        public static  object ChangeType(object value, Type type)
        {
            try
            {
                if (value == null && type.IsGenericType) return Activator.CreateInstance(type);
                if (value == null) return null;
                if (type == value.GetType()) return value;
                if (type.IsEnum)
                {
                    if (value is string)
                        return Enum.Parse(type, value as string);
                    else
                        return Enum.ToObject(type, value);
                }
                if (!type.IsInterface && type.IsGenericType)
                {
                    Type innerType = type.GetGenericArguments()[0];
                    object innerValue = ChangeType(value, innerType);
                    return Activator.CreateInstance(type, new object[] { innerValue });
                }
                if (value is string && type == typeof(Guid)) return new Guid(value as string);
                if (value is string && type == typeof(Version)) return new Version(value as string);
                if (!(value is IConvertible)) return value;
                return Convert.ChangeType(value, type);
            }
            catch (Exception ex)
            {
                return Activator.CreateInstance(type);
            }
          
        }
    }
}